package pl.edu.agh.gameserv.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.*;

import javax.jws.WebMethod;
import javax.jws.WebService;

import pl.edu.agh.gameserv.gameproviderapi.GameLogic;
import pl.edu.agh.gameserv.gameproviderapi.GameProvider;
import pl.edu.agh.gameserv.serverapi.GameNotReadyException;
import pl.edu.agh.gameserv.serverapi.GameStatus;
import pl.edu.agh.gameserv.serverapi.NotMyMoveException;

/**
 * Session Bean implementation class ServerImpl
 */
@Singleton
@LocalBean
@WebService
public class ServerImpl {
	@EJB
	private GameProvider provider;
	private int currGameHandleId = 0;
	private HashMap<String, ArrayList<GameHandleImpl>> waitingHandles;
	private List<GameContainer> runningGameContainers;
	private Map<Integer, GameHandleImpl> gameHanlders;

	/**
	 * Default constructor.
	 */
	public ServerImpl() {
		waitingHandles = new HashMap<String, ArrayList<GameHandleImpl>>();
		runningGameContainers = new ArrayList<GameContainer>();
		gameHanlders = new HashMap<Integer, GameHandleImpl>();
	}

	@WebMethod
	public List<String> getGameTypes() {
		List<String> result = new ArrayList<String>();
		result.add(provider.getGameType());
		return result;
	}

	@WebMethod
	public int startGame(String type, String userName) {
		ArrayList<GameHandleImpl> otherWaiting = waitingHandles.get(type);

		if (otherWaiting == null) {
			otherWaiting = new ArrayList<GameHandleImpl>();
			waitingHandles.put(type, otherWaiting);
		}

		GameHandleImpl handle = new GameHandleImpl(userName);
		otherWaiting.add(handle);

		if (otherWaiting.size() == provider.getGameUserCount()) {
			GameLogic game = provider.createGame();

			GameContainer container = new GameContainer(game, type, otherWaiting);
			runningGameContainers.add(container);

			waitingHandles.remove(type);
		}

		gameHanlders.put(++currGameHandleId, handle);
		return currGameHandleId;
	}

	/*
	 * gdy user nie ma towarzyszy do gry i czeka, co jakis czas wywoluje ta
	 * metode zeby sprawdzic czy ktos sie pojawil
	 */
	@WebMethod
	public GameStatus getGameStatus(int gameHandleId) {
		if (!gameHanlders.containsKey(gameHandleId) )
			return GameStatus.Finished;
		return gameHanlders.get(gameHandleId).getStatus();
	}

	@WebMethod
	public GameStatus makeMove(int gameHandleId, String move) throws GameNotReadyException, NotMyMoveException,
			pl.edu.agh.gameserv.serverapi.IllegalMoveException {
		if (gameHanlders.get(gameHandleId).gameContainer.handles.size() < provider.getGameUserCount())
			return exit(gameHandleId);
		gameHanlders.get(gameHandleId).move(move);
		return getGameStatus(gameHandleId);
	}

	@WebMethod
	public String getScore(int gameHandleId) {
		if (!gameHanlders.containsKey(gameHandleId) || gameHanlders.get(gameHandleId).gameContainer.handles.size() < provider.getGameUserCount())
			return "Jeden z graczy opuścił grę.";
		return gameHanlders.get(gameHandleId).getScore();
	}

	@WebMethod
	public int getMyNumber(int gameHandleId) {
		return gameHanlders.get(gameHandleId).getMyNumber();
	}

	@WebMethod
	public String[][] getSituation(int gameHandleId) {
		return gameHanlders.get(gameHandleId).getSituation();
	}

	@WebMethod
	public String getUserName(int gameHandleId, int number) {
		return gameHanlders.get(gameHandleId).getUserName(number);
	}

	@WebMethod
	public GameStatus exit(int gameHandleId) {
		GameHandleImpl gameHandle = gameHanlders.get(gameHandleId);
		GameContainer gameContainer = gameHandle.gameContainer;
		if (gameContainer.handles.size() == 1)
			runningGameContainers.remove(gameHandle.gameContainer);
		gameHanlders.remove(gameHandleId);
		gameContainer.handles.remove(gameHandle);
		return GameStatus.Finished;
	}
}
